Доп. опции SN:   A B C D E F G H I K L M O Q R T V W X
При помощи расширения стандартного ресивера !!SN были введены основные новые команды для ERA.
См. описание стандартных команд !!SN

Ресивер SN: новые команды


Все команды ERA могут работать со следующими элементами ERM:

Также, стоит отметить, что в отличии от стандартных z-переменных (длиной до 511 символов) строковые литералы ERA (^…^ или ^%S(…)^) могут иметь длину до 1млн. символов.

Более того, для всех команд новых ресиверов ERA (SN/MP/RD) реализована поддержка:

Примеры (показать)
  1. !!SN:W^Gold^/y1 W^Gold^/d-500 W^Gold^/d*11 W^Gold^/d:10; Gold = y1 -500 * 1.1
  2. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3. !!SN:W^report^/^Сегодня мы напоролись на чужаков... Это были ^;
  4. !!SN:W^report^/d&^орки!^;
  5. !!IF:M^%S(report)^;
На экране мы увидим:Сегодня мы напоролись на чужаков... Это были орки!

Ядро ERA передаёт командам набор целых чисел (4 байта каждое). В случае строк или синтаксиса получения значения, эти числа представляют собой адреса переменных. Адрес переменной – числовое значение, описывающее местоположение данных в оперативной памяти.
Максимальное количество параметров команды: 64.
Пример (показать)

  1. !!SN:Xv1; передать число в v1
  2. !!SN:X?v1; передать адрес переменной v1
  3. !!SN:Xz1; передать адрес переменной z1
  4. !!SN:X^текст^; сохранить текст и передать его адрес
  5. !!SN:Xe1 X?y1; перевести значение из float формата в dec


SN:L
Подгрузка динамической библиотеки (DLL)

L путь к библиотеке /? описатель загруженной библиотеки

Пример:

  1. !!SN:L^HD_WOG.dll^/?y2; игра с HD_mod? (y2=0 – игра без HD)


SN:A
Получить адрес машинной функции из библиотеки

A описатель загруженной библиотеки / название функции /? адрес функции

Пример:

  1. !!SN:L^kernel32.dll^/?y1;
  2. !!SN:Ay1/^lstrcpyA^/?y2;


SN:E
Выполнить машинную функцию

Соглашение о вызове:
   0  (PASCAL)
   1  (CDECL или STDCALL)
   2  (THISCALL)
   3  (FASTCALL)

По умолчанию от функции ожидается целочисленный результат, который будет помещён в переменную v1. Если же функция возвращает вещественный результат, то к номеру соглашения нужно прибавить 4 (сам же результат сохранится в e1). Все системные библиотеки используют соглашение STDCALL.

E адрес функции / соглашение о вызове /аргументы…

Примеры:

  1. !!SN:L^kernel32.dll^/?y1;
  2. !!SN:Ay1/^lstrcpyA^/?y2;
  3. !!SN:Ey2/1/z1/z2; Скопировать содержимое z2 в z1. Аналог !!VRz1:Sz2;
Получить ID текущего игрового диалога:
  1. !!SN:L^Era.dll^/?y2; получили описатель библиотеки ERA в y2
  2. !!SN:Ay2/^GetGameState^/?y3; y3 - адрес функции GetGameState
  3. !!SN:Ey3/1/?y4/?y5; y4 - ID родительского диалога, y5 - ID текущего диалога
Вычисление корня квадратного на примере стороннего модуля:
  1. !!SN:L^math.era^/?y1;
  2. !!SN:Ay1/^sqrt^/?y2;
  3. !!VRe2:S169; будем извлекать квадратный корень из 169
  4. !!SN:Ey2/5/e2; здесь 5 - соглашение STDCALL (1+4)
  5. !!IF:M^e1=%E1^;


SN:F
Выполнить функцию с указанными аргументами для её выполнения из библиотеки era.dll или kernel32.dll (ERA сама выберет нужную библиотеку для функции и закэширует её адрес по имени).
Нет необходимости, в большинстве случаев, использовать последовательность команд SN:L→SN:A→SN:E.

Используется соглашение STDCALL.

F название функции / аргументы ф-ции…

Примеры:

  1. !!SN:F^ReadStrFromIni^/^key^/^section name^/^Data\test.ini^/?z2; аналог команды UN:N6
  2. !!SN:F^CopyFileA^/^heroes3.ini^/^heroes3.ini.bak^/0; сделать резервную копию файла настроек игры
  3. !!SN:F^GetButtonID^/^testBtn^; v1 получит ID кнопки
  4. !!SN:F^PluginExists^/^era_hooker^; если v1=0, то плагин не найден


SN:D
Перерисовать (обновить) экран героя, города, встречи двух героев, карты приключений.
Комментарий: команда более безопасна, чем аналогичная ей UN:R.
Команду следует использовать, непосредственно, в указанных выше игровых окнах, т.к. каждому игровому окну соответствует своя функция обновления и только для него.
Пример:

  1. !?CM2; экран героя
  2. !!CM:I?y1 T?y2;
  3. !!FU|y1<>30720/y2<>512:E; если кликнули ПКМ на кнопке Выход
  4. !!HE-1:L4/148; сделать текущему герою лицо как у Гелу
  5. !!SN:D;


SN:G[имя]
Переход на определённую команду текущего триггера.

На сегодня команда SN:G считается устаревшей и её использование в скриптах крайне не рекомендуется!
Изначально команда создавалась как промежуточный вариант выполнения быстрых циклов. Сейчас предпочтительнее для этих целей использовать связку !!if / !!re.

Для выполнения переходов реализованы командные «ярлыки» (метки), которые заменяются на порядковый номер ресивера внутри текущего триггера, перед которым они стоят (отсчёт начинается с 0). В «счётчик» команд попадают все !!XX-подобные ресиверы. Самим меткам порядковый номер, как команде внутри триггера, не присваивается.
Синтаксис использования следующий:

[имя_метки] – использование метки (будет заменено номером ресивера, для которого метка объявлена)
[:имя_метки] – объявление метки (текущий номер ресивера запоминается и связывается с именем метки)

В качестве имени метки допускается любой произвольный текст. Использовать метки можно как до, так и после их объявления.
Метки используются только с командой SN:G для выполнения циклов и условий.
Пример:

  1. ...
  2. !!VRv1:S0 R10;
  3. !!SN&v1>5:G[прыжок];
  4. !!FU:E; "ERM-забор" =)
  5. [:прыжок]
  6. !!IF:M^Вы перепрыгнули забор :)^;
ВАЖНО: не разрешается использовать SN:G для "прыжков" как из структурных блоков, так и в структурные блоки.
Пример:
Для прерывания цикла есть команда !!br. Эмулировать SN:G можно так:
  1. !!re i/1/1; выполнить один раз блок
  2. ...
  3. !!br&условие:; выход из блока по условию
  4. ...
  5. !!en:;

Старый синтаксис:
SN:G# - переход на команду # (0…) текущего триггера.
Пример (показать)

  1. !?CM0;
  2. ; ПКМ на карте приключений
  3. ;0 !!SN:G2; перейти на команду №2
  4. ;1 !!IF:M^Данный текст вы никогда не увидите!^;
  5. ;2 !!IF:M^Сейчас вы читаете это текст?^;
  6. ; Нумерация команд триггера приведена для наглядности


SN:H^xxx^…
Команда позволяет работать с названиями/подсказками/описаниями без необходимости хранить текст в выделенных для этого z-переменных.
На данный момент реализованы следующие типы команд SN:H:

Режим получения текста работает со всеми этими типами команд, давая возможность получать актуальный текст/описание в z-переменные для последующего вывода:

  1. ...
  2. !!SN:H^monname^/13/2/?z2; получить в z2 описание архангела
Для удаления (актуальных значений или установленных ранее через SN:H) или восстановления (стандартный текст) подсказок/описания используйте синтаксис ^-xxx^
Пример:
  1. !!SN:H^-spec^/5/2/^^; восстановить описание специальности Сорше


H^monname^/#1/#2/^текст^
H^monname^/#1/#2/?z#
Изменение имени существ, их описания.

        #1 – номер монстра
        #2 – тип текста:
	0 – имя монстра в ед.ч.
	1 – имя монстра во мн.ч.
	2 – специальный текст (описание)
Комментарий: команда отличается от аналогичной ей UN:G1 тем, что не требует использования z-переменныx.

Пример:

  1. Изменим имена и описания копейщиков:
  2. !?PI;
  3. !!SN:H^monname^/0/0/^Слабый^;
  4. !!SN:H^monname^/0/1/^Больные^; переименовать копейщика (1 = мн.ч.)
  5. !!SN:H^monname^/0/2/^Разносит заразу^; сменить описание (2) копейщика


H^object^/X/Y/L/^текст^
Установить подсказку для объекта на карте в координатах X Y L.
H^object^/#1/#2/^текст^
Установить подсказку для объекта определённого типа/подтипа.

        #1 – тип (-1 = пропустить) 
        #2 – подтип (-1 = пропустить)

Если используется несколько вариантов установки подсказок для одного объекта, то приоритет поиска подсказки таков:

  1. объект с точными координатами
  2. объект с указанными типом/подтипом
  3. объект с указанным типом и подтипом -1
  4. объект с типом -1 и указанным подтипом
  5. объект c типом/подтипом как -1
Комментарий: команда отличается от схожих с ней команды OB:H и ресивера HT тем, что не требует использования z-переменныx.

Пример:

  1. !!VRz1:S^{Обледенелое озеро}
  2. Осторожно, лёд очень тонкий!^;
  3. !!SN:H^object^/121/-1/^%Z1^; установить свою подсказку для объекта 121 (замёрзшее озеро)


H^secskill^/#1/#2/^текст^
H^secskill^/#1/#2/?z#
Возможность установки текста вторичных навыков:

        #1 – вторич.навык (0..27)
        #2 – тип текста:
	0 – имя навыка
	1 – базовый уровень (описание)
	2 – продвинутый уровень (описание)
	3 – экспертный уровень (описание)
Комментарий: команда отличается от аналогичной ей UN:G0 тем, что не требует использования z-переменныx.

Пример:

  1. !!VRz5:S^тест^;
  2. !!SN:H^secskill^/21/0/^%Z5^; установить навыку обучение (21) название из z5
  3. !!IF:M1/z5; показать текст из z5
  4. !!SN:H^-secskill^/21/0/^^; вернуть стандартное название обучения
  5. !!SN:H^secskill^/21/0/?z5; получить в z5 текущее название навыка
  6. !!IF:M1/z5; показать текст из z5
Вы получите два разных сообщения:тест и Обучение


H^spec^/#1/#2/^текст^
H^spec^/#1/#2/?z#
Настроить свой текст для специализации героя

        #1 – герой
        #2 – тип текста для специализации:
	0 – название (не используется в игре)
	1 – краткое описание (не используется в игре)
	2 – полное описание
Комментарий: команда отличается от аналогичной ей UN:G2 тем, что не требует использования z-переменныx.

Пример:

  1. !!HE-1:N?y1 B0/?z1; получить номер и имя текущего героя
  2. !!SN:H^spec^/y1/2/^{~red}Коддер{~}
  3. Специализация %Z1: лютый коддинг!^; установить описание (2) спецухи этому же герою


SN:I
Динамическая интерполяция строковых переменных.
Команда может использоваться для интерполяции строковых переменных, получамых из внешних источников, таких как ini-файлы и команда SN:T (хотя её использование рекомендуется только для отладки и портирования).

I строковая переменная /? z#

Пример:
Допустим, в переменной z2 хранится следующее: %Y5 %V996 текст %Z5
Нам надо увидеть, какие значения каждая переменная содержит на данный момент.
Для этого мы используем следующее:

  1. !!SN:Iz2/?z3;
Теперь z3 содержит всю информацию из z2, включая все значения интерполированных переменных.


SN:O?X/?Y/?L
Получить координаты входа объекта на карте.
Команде передаются три числовые переменные с координатами объекта, в которые и будут записаны координаты входа объекта.
Комментарии (показать)

Пример:
Давайте узнаем координаты входа объекта, кликнув на другой части объекта…
  1. !?CM0; клик на карте
  2. !!CM:R0 P?y1/?y2/?y3; получаем координаты объекта
  3. !!VRv2:Cy1/y2/y3; сохраняем копию координат в v2/v3/v4
  4. !!SN:O?y1/?y2/?y3; получаем координаты входа объекта
  5. !!IF:M0/4/^%V2 %V3 %V4 => %Y1 %Y2 %Y3^; сравниваем наглядно


SN:Q
Прервать обработку текущего события
Комментарий: команда отличается от FU:E тем, что прерывает всю цепочку однотипных триггеров.

Пример:

  1. !?FU40000;
  2. !!SN:Q; покинуть цепочку триггеров FU40000
  3. !?FU40000;
  4. !!IF:M^это сообщение никогда не будет показано^;
  5. !?CM0;
  6. !!FU40000:P; вызвать функцию 40000


SN:R
Подменяет в игре "на лету" имена ресурсов.

Используется соглашение STDCALL.

R ^старое имя файла^ / ^новое имя файла^

Для сброса подмены файла укажите пустое значение вместо параметра "новое имя".
Комментарии (показать)

Команда представляет собой обёртку над экпортируемой функцией RedirectFile из era.dll. Если более детально, то SN:R ни что иное как:
  1. !!SN:L^Era.dll^/?y1 Ay1/^RedirectFile^/?y2 Ey2/1/^старое^/^новое^;
Все подмены файлов локальны, запоминаются в сохранениях игры и отменяются при выходе из игрового сценария (карты).
Игра выгружает неиспользуемые ресурсы, поэтому большинство ресурсов могут динамически подменяться, пока вы играете.
Если ресурс используется в Окне героя, выполняйте подмену перед тем, как откроется это окно (т.е. до кэширования ресурсов).
Пользовательские игровые фоны могут так же быть внедрены, давая возможность игроку переключать темы прямо во время игры (необходимо загрузить сохранение игры для визуального обновления).
Указав шаблон *.mp3 для параметра "старое имя" подмена произойдёт для всех mp3-файлов сразу.

Примеры:

  1. !#SN:R^cgriff.def^/^croc.def^; пусть Грифоны выглядят как Птицы Рух (только боевая модель)
  2. !!SN:R^SNOW.MP3^/^my_snow.mp3^; подмена родной темы для поверхности "Снег" на свой трэк


SN:T^имя^/?z#/#1/?$1.../#7/?$7
Позволяет получать переводы строк по ключам (произвольным уникальным строковым идентификаторам).
В json-файлах хранятся пары вида «Ключ - Значение», где значением является текст перевода с опциональными параметрами.

	(имя) – имя ключа
	z# – z-переменная для получения результата
	#1 – наименование параметра 1
	$1 – значение параметра 1
	…
	…
	#7 – наименование параметра 7
	$7 – значение параметра 7
Пример (показать)
  1. !!OW:R-1/6/?y1; y1 = кол-во золота у игрока
  2. !!SN:T^test.gold_amount_report^/?z2/^gold^/y1;
  3. !!IF:M^%Z2^; покажет "У вас осталось 12850 золотых. Неплохо!"
Мой test.json:
{
  "test.gold_amount_report": "У вас осталось @gold@ золотых. Неплохо!"
}

См. также: Выдержка из истории изменений ERA по json-файлам


SN:X
Доступ к параметрам новых событий

X до 16 параметров

Новые события ERA и добавляемые модулями события нуждаются в возможности обмениваться данными со скриптами. Эту возможность обеспечивает команда , выступающая в качестве хранилища значений. Тип значений определяется способом работы с ними. Так, можно установить в слот 0 значение 5, а потом получить его в вещественную e-переменную. Поскольку работа происходит на машинном уровне, то в e-переменной окажется вовсе не 5, а неопределённый мусор. В случае получения строковой переменной (текста), команда трактует значение в слоте как адрес. Поэтому, !!SN:X0; !!SN:X?z1; приведёт к вылету, т.к. по адресу 0 нет никакой строки.
Пример:

  1. !!SN:Xz1; записать в 1ый параметр адрес строковой переменной z1
  2. !!SN:X?y1; получить в y1 адрес z1
Т.к. в ERA переменные x1..x16 доступны для любых триггеров, SN:X параметры и есть x1..x16.
Замечание: на данный момент команда SN:X устарела, т.к. параметры событий можно читать/писать, обращаясь напрямую к x1..x16.
Пример:
  1. !?(OnRecruitDlgRecalc);
  2. !!VRx1:S777; = !!SN:X777;
  3. !!VRy2:Sx1; = !!SN:X?y2;
  4. !!VRy3:Cx1/x2; = !!SN:X?y3/?y4;
Команду X целесообразно использовать только для редко требуемых операций по низкоуровневому преобразованию типов или получению адресов…
  1. !!SN:X?y1 Xs^мой текст^ X?y2 Xy1; получить в y2 адрес именованной переменной
  2. Описание каждой команды в отдельности:
  3. » X?y1; сохранить значение 1го параметра триггера
  4. » Xs^мой текст^; передать в x1 адрес именованной строки
  5. » X?y2; получить адрес именованной переменной
  6. » Xy1; возвращаем значение 1го параметра триггера


Работа с дополнительной памятью

SN:M…

ERM переменные статичны и ограничены в количестве. Статичность приводит к невозможности организовывать динамические структуры данных (например, списки), для которых нужны функции выделения и освобождения памяти, а ограниченное количество ведёт к необходимости строгого учёта индексов без возможности выйти за их пределы. Более того, ERM строки в виде z-переменных занимают ровно 512 байт каждая в независимости от размера их содержимого. ERA предоставляет программисту до 2 млрд. слотов под массивы новых переменных (числовых или строковых). Размер массивов может изменяться средствами ERM. Поскольку работа с динамическими структурами предполагает автоматическое выделение номеров слотов, то такая возможность присутствует. Слоты с положительными индексами принадлежат пользователю, а с отрицательными используются при автовыделении памяти.
Замечание: команды SN:M не поддерживают работу переменных с косвенными ссылками…

  1. !!SN:My1/y2/xy3; вызовет ошибку ЕРМ
  2. Безопасный способ:
  3. !!VRy4:Sxy3;
  4. !!SN:My1/y2/y4;


M#
Удаление слота памяти

M номер слота, начиная с 0

Пример:

  1. !!SN:M5; удалить 6й слот


M#1/$2
Установка/получение размера слота
(Размер слота – это количество элементов в массиве)

        #1 – номер слота
        $2 – кол-во элементов

Команда возвращает -1, если слот не существует.
Пример:

  1. !!SN:M2/5; установить количество элементов в слоте 2 равное 5.
  2. !!SN:My1/?y2; получить размер слота y1 в переменную y2.


M#1/#2/$3
Работа со значениями элементов слотов

        #1 – номер слота
        #2 – номер элемента, начиная с 0
        $3 – значение
Пример:
  1. !!SN:M1/3; размер слота 1 = 3 элемента
  2. !!SN:M1/0/111 M1/1/222 M1/2/333; содержимое слота 1: 111, 222, 333
  3. !!SN:M1/1/?y5; y5 - содержимое 1-го элемента слота 1
  4. !!IF:M^%Y5^; покажет: "222"


M#1/?#2/#3
Получение адреса элемента слота

        #1 - номер слота
        #2 - адрес элемента (только получение)
        #3 - номер элемента

Комментари: при удалении слота или изменении его размера – адрес станет недействительным!
Примеры (показать)

  1. !!SN:M1/?y1/2; y1 содержит адрес 2-го элемента слота 1
А вот другой пример, когда требуется скопировать строковое значение из массива в массив напрямую.
Как уже было сказано ранее, все команды ERA получают параметры в виде 4-байтовых чисел. Для строк это обычно адрес первого символа. Когда мы пишем z1, команда получает адрес этой переменной. Когда строковое значение ^текст^ – строка сперва сохраняется во временном буфере, затем команде передаётся её адрес, после чего буфер освобождается..
  1. !!SN:M(src array)/?y1/(src index); записывает в y1 адрес первого символа строки в указанном массиве
  2. !!SN:M(dst array)/(dst index)/y1; устанавливает новое значение элемента массива (команде передаётся адрес строки)
  3. ; команды ERA, принимающие строки, одинаково хорошо переваривают и адреса pchar'ов
Таким образом, длинные строки (>512 байт) можно копировать между собой и использовать как буфер для накопления:
  1. !!SN:M../../d&^ соединение строк^;


M#1/#2/#3/#4
Создание нового слота

        #1 – номер слота: "-1" для автовыделения свободного номера и помещения его в v1
        #2 – кол-во элементов в слоте
        #3 – тип элементов: 0 (число) и 1 (строка)
        #4 – запоминать ли значения в сохранёнках:
	= 0 (нет, при загрузке игры содержимое элементов будет представлять собой случайный мусор)
	= 1 (да, содержимое нужно сохранять как есть)

Комментарий: старое содержимое слота (если оно было), уничтожается.
Если значения в сохранениях не запоминать (#4=0), то экономится место в файле и возрастает скорость сохранения.
Пример:

  1. !!SN:M0/4/1/1; выделить массив из 4-х строк в слоте 0. Сохранять их содержимое при загрузке
  2. !!SN:M0/2/^привет^; установить значение 2-й строки слота 0
  3. !!SN:M0/3/^мир^; установить значение 3-й строки слота 0
  4. !!SN:M0/2/?z1 M0/3/?z2; получить значения 2-й и третьей строк в z1, z2
  5. !!IF:M^%Z1 %Z2^; выведет "привет мир"
  6. !!SN:M0; удалить слот 0
  7. !!SN:M-1/0/0/0; выделить пустой слот под временный массив чисел
  8. !!VRy1:S1 R6; сгенерировали случайное число 1..7
  9. !!SN:Mv1/y1; установили размер нового слота в это число
  10. !!VRy1:-1; y1 - индекс последнего элемента в слоте
  11. !!SN:Mv1/y1/777; значение последнего элемента слота - 777


SN:K…
Команды SN:K работают как со строками (текстовыми переменными), так и с их адресами в памяти. Это делает SN:K более низкоуровневой и функциональной, чем схожие с ней по некоторым действиям команды VR:M#.

K#1/?#2
Получение размера строки (включая пробелы)

K строка или её адрес /? размер строки

Пример:

  1. !!VRz1:S^123 4^;
  2. !!SN:Kz1/?y1; y1 = 5


K#1/#2/$3
Работа с символами строки

K строка или её адрес / номер символа, начиная с 0 /[?] значение символа

Пример:

  1. !!VRz1:S^XYZ^;
  2. !!SN:Kz1/2/^L^; установить 2-й символ строки z1 в "L"
  3. !!IF:M^%Z1^; покажет нам "XYL"
Замечание: синтаксис получения символа в $3 параметр работает некорректно.


K#1/#2/#3/#4
Копирование блока памяти

K кол-во байт / адрес источника / адрес приёмника / произвольное значение

Комментарий: поддерживаются числовые и строковые переменные.

Пример:

  1. !!SN:K12/?v1/?y1/1; скопировать 12 байт (3 числа по 4 байта) из v1, v2, v3 в y1, y2, y3
  2. !!VRv1:C1/2/3; v1 = 1, v2 = 2, v3 = 3
  3. !!SN:K12/?y1/?v1/1; восстановить значения v1, v2, v3


Работа с ассоциативной памятью

SN:W[…]

Очень часто бывает нужно завести переменные для конкретных героев, конкретных клеток карты или объектов по запросам игрока.
Выделение статической памяти для всех героев, всех объектов или всех клеток обладает существенными недостатками: чрезмерное потребление памяти, замедление процесса сохранения игры, ограниченность размеров.
Все эти проблемы решаются при работе с глобальным хранилищем пар типа «Ключ - Значение», напоминающем ini-файлы.
Каждому ключу может соответствовать 1 числовое и 1 строковое значение.
Значения 0/пусто не записываются в сохранения, что позволяет экономить место.
При запросе несуществующего ключа будет возвращено 0/пусто, в зависимости от типа приёмника.
Пример:
Давайте создадим ключ и запишем в него значения разных типов, при этом они пересекаться не будут:

  1. !!SN:W^имя^/y1 W^имя^/z1;
  2. !!SN:W^имя^/?y2 W^имя^/?z2; y2=y1, z2=z1


W
Полная очистка ассоциативной памяти

W^имя^/$
Работа с переменной

W имя переменной /[?] значение переменной

Пример:
Пусть щелчок правой кнопкой мыши на карте приключений приводит к отображению количества щелчков по данной клетке.
Фактически, это аналог команды !!PO по требованию.

  1. !?CM0;
  2. !!CM:R0 P?y1/?y2/?y3;
  3. !!SN:W^Map%Y1/%Y2/%Y3^/?y4;
  4. !!VRy4:+1;
  5. !!IF:L^{~gold}Вы щёлкнули на этой клетке %Y4 раз(а){~}^;
  6. !!SN:W^Map%Y1/%Y2/%Y3^/y4;
Замечание: внутри %I() нельзя использовать символ процентов (%).

W^имя^
Удаление переменной